package com.example.basewarehouse.net;

import android.os.Environment;


import com.example.basewarehouse.mvp.BaseResponse;
import com.example.basewarehouse.net.Interceptor.HttpRequestInterceptor;
import com.example.basewarehouse.net.Interceptor.OfflineCacheInterceptor;
import com.example.basewarehouse.utils.TS;

import java.io.File;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Action;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import okhttp3.Cache;
import okhttp3.OkHttpClient;
import okhttp3.ResponseBody;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;


public class RetrofitUtils {

    private static RetrofitUtils retrofitUtils;
    private static Retrofit retrofit;
    private static RetrofitApiService retrofitApiService;
    private static OkHttpClient okHttpClient;
    private static ArrayList<String> oneNetList;


    public static RetrofitUtils getRetrofitManager() {
        if (retrofitUtils == null) {
            synchronized (RetrofitUtils.class) {
                if (retrofitUtils == null) {
                    retrofitUtils = new RetrofitUtils();
                    oneNetList = new ArrayList<>();
                }
            }
        }
        return retrofitUtils;
    }

    private RetrofitUtils(){
        initOkHttpClient();
        retrofit = new Retrofit.Builder()
                .baseUrl("") // 设置 网络请求 Url
                .addConverterFactory(GsonConverterFactory.create()) //设置使用Gson解析(记得加入依赖)
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .client(okHttpClient)
                .build();
    }

    public static RetrofitApiService getRetrofitApiService(){
        retrofitApiService = retrofit.create(RetrofitApiService.class);
        return retrofitApiService;
    }

    private void initOkHttpClient() {
        okHttpClient = new OkHttpClient.Builder()
                //设置缓存文件路径，和文件大小
                .cache(new Cache(new File(Environment.getExternalStorageDirectory() + "/okhttp_cache/"), 50 * 1024 * 1024))
                .connectTimeout(10, TimeUnit.SECONDS)
                .readTimeout(10, TimeUnit.SECONDS)
                .writeTimeout(10, TimeUnit.SECONDS)
                .addInterceptor(new HttpRequestInterceptor())
                //设置在线和离线缓存
                .addInterceptor(OfflineCacheInterceptor.getInstance())
                .build();
    }

    public static <T> Disposable observe(int reqCode, Observable<BaseResponse<T>> observable, CallBackListener<T> callBackListener) {
        return observable
                .subscribeOn(Schedulers.io())
                .doOnSubscribe(new Consumer<Disposable>() {
                    @Override
                    public void accept(Disposable disposable) throws Exception {
//                        if (showDialog) {
//                            mvpView.showLoading(message);
//                        }
                        if(callBackListener!=null){
                            callBackListener.onBeforeResponse();
                        }
                    }
                })
                .retryWhen(new RetryWithDelay(2,3000))//总共重试2次，重试间隔3000毫秒
                .map(new Function<BaseResponse<T>, T>() {
                    /**
                     * Apply some calculation to the input value and return some other value.
                     *
                     * @param tBaseResponse the input value
                     * @return the output value
                     * @throws Exception on error
                     */
                    @Override
                    public T apply(BaseResponse<T> tBaseResponse) throws Exception {
                        if(tBaseResponse.success()){
                            if(tBaseResponse.data!=null){
                                return tBaseResponse.data;
                            }else {
                                throw new HttpException(tBaseResponse.code,tBaseResponse.msg);
                            }
                        }else {
                            throw new HttpException(tBaseResponse.code,tBaseResponse.msg);
                        }
                    }
                })
                .doFinally(new Action() {
                    @Override
                    public void run() throws Exception {

                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<T>() {
                    @Override
                    public void accept(T t) throws Exception {
                        if(callBackListener!=null){
                            callBackListener.onSucessData(reqCode,"",t);
                        }
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {
                        try {
                            int status = ((HttpException)throwable).status;
                            String msg=((HttpException)throwable).msg;
                            if(status==200){
                                if(callBackListener!=null){
                                    callBackListener.onSucessData(reqCode,"",null);
                                }
                            }else if(status==401){
                                if(callBackListener!=null){
                                    callBackListener.onLogin(reqCode,msg);
                                }
                            }else {
                                TS.show(msg);
                                if(callBackListener!=null){
                                    callBackListener.onFailure(reqCode,msg);
                                }
                            }
                        }catch (Exception e){
                            //返回了没有实体的数据
                            if(callBackListener!=null){
                                callBackListener.onSucessData(reqCode,"",null);
                            }
                        }

                    }
                });
    }


    /**
     * 这是下载文件
     */
    public void downLoadFile(String url, final String destDir, final String fileName, final FileDownLoadObserver<File> fileFileDownLoadObserver) {
        retrofitApiService.downloadFile(url)
                .subscribeOn(Schedulers.io())
                .observeOn(Schedulers.io())
                .map(new Function<ResponseBody, File>() {
                    @Override
                    public File apply(ResponseBody responseBody) throws Exception {
                        return fileFileDownLoadObserver.saveFile(responseBody, destDir, fileName);
                    }
                })
//                .compose(mvpView.bindLifecycle())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(fileFileDownLoadObserver);

    }


    public void downLoadFile(String url, final String destDir, final String fileName, final long currentLength, final FileDownLoadObserver<File> fileFileDownLoadObserver) {
        String range = "bytes=" + currentLength + "-";
        retrofitApiService.downloadFile(url,range)
                .subscribeOn(Schedulers.io())
                .observeOn(Schedulers.io())
                .map(new Function<ResponseBody, File>() {
                    @Override
                    public File apply(ResponseBody responseBody) throws Exception {
                        return fileFileDownLoadObserver.saveFile(responseBody, destDir, fileName,currentLength);
                    }
                })
//                .compose(mvpView.bindLifecycle())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(fileFileDownLoadObserver);
    }

}
